#include "StdAfx.h"
#include <MyControls/TimeControls.h>
#include <MyControls/Sequence.h>
#include <MyControls/SequenceView.h>
#include <MyControls/Resource.h>
#include <MyFC/Utility.h>
#include <xtd/string>
#include <MyControls/App.h>

namespace My {

const int Gap = 8;

// TimeEditControl

TimeEditControl::TimeEditControl()
	: m_pSequence(0)
{
}

TimeEditControl::~TimeEditControl()
{
	SetSequence(0);
}

bool TimeEditControl::IsEmpty() const
{
	return m_pSequence == 0 ||
		m_pSequence->IsEmpty();
}

void TimeEditControl::SetSequence(Sequence * ptr)
{
	if (m_pSequence != ptr) {
		if (m_pSequence != 0)
			m_pSequence->Detach(this);
		m_pSequence = ptr;
		if (m_pSequence != 0)
			m_pSequence->Attach(this);
		HandleUpdateUI();
	}
}

bool TimeEditControl::GetText(String & s)
{	
	if (IsEmpty())
		return false;
	s = xtd::string(m_pSequence->GetPreviewFrame());
	return true;
}
	
void TimeEditControl::SetText(const String & s)
{
	if (IsEmpty())
		return;
	int value;
	if (xtd::string::full_convert(s, value))
		m_pSequence->SetCurrentFrame(value);
}

void TimeEditControl::ProcessEvent(Event & e)
{
	if (e.Is<Sequence::Event>()) {
		HandleUpdateUI();
		Invalidate();
		Update();
	} else
		Container::ProcessEvent(e);
}

void TimeEditControl::HandleUpdateUI()
{
	SetEnabled(!IsEmpty());
	UpdatePreferredSize();
}

// FramerateEditControl

FramerateEditControl::FramerateEditControl()
	: m_pSequenceView(0)
{
}

FramerateEditControl::~FramerateEditControl()
{
}

bool FramerateEditControl::IsEmpty() const
{
	return m_pSequenceView == 0 ||
		m_pSequenceView->IsEmpty();
}

void FramerateEditControl::SetSequenceView(SequenceView * ptr)
{
	if (m_pSequenceView != ptr) {
		if (m_pSequenceView != 0)
			m_pSequenceView->Detach(this);
		m_pSequenceView = ptr;
		if (m_pSequenceView != 0)
			m_pSequenceView->Attach(this);
		HandleUpdateUI();
	}
}

bool FramerateEditControl::GetText(String & s)
{	
	if (IsEmpty())
		return false;
	s = xtd::string(m_pSequenceView->GetFramerate());
	return true;
}
	
void FramerateEditControl::SetText(const String & s)
{
	if (IsEmpty())
		return;
	float value;
	if (xtd::string::full_convert(s, value))
		m_pSequenceView->SetFramerate(value);
}

void FramerateEditControl::ProcessEvent(Event & e)
{
	if (e.Is<SequenceView::FramerateChange>()) {
		HandleUpdateUI();
		Invalidate();
		Update();
	} else
		Container::ProcessEvent(e);
}

void FramerateEditControl::HandleUpdateUI()
{
	SetEnabled(!IsEmpty());
	UpdatePreferredSize();
}

// TimeControls

ToolButtonInfo Buttons[] = {
	{ID_TIME_FIRST_FRAME, "TIME_FIRST_FRAME"},
	{ID_TIME_PREVIOUS_FRAME, "TIME_PREVIOUS_FRAME"},
	{ID_TIME_PLAY_BACKWARD, "TIME_PLAY_BACKWARD"},
	{ID_TIME_PAUSE, "TIME_PAUSE"},
	{ID_TIME_PLAY_FORWARD, "TIME_PLAY_FORWARD"},
	{ID_TIME_NEXT_FRAME, "TIME_NEXT_FRAME"},
	{ID_TIME_LAST_FRAME, "TIME_LAST_FRAME"},
	{0, 0},
	{ID_TIME_LOOP, "TIME_LOOP"},
	{0, 0},
	{ID_TIME_FOLLOW, "TIME_FOLLOW"}
};

TimeControls::TimeControls(bool FollowButton) : 
	m_Buttons(ToolBar::HORIZONTAL), m_pSequenceView(0)
{
	Add(&m_Buttons);
	m_Buttons.SetButtonSize(CSize(19, 15));
	m_Buttons.SetButtons(Buttons, sizeof(Buttons) / sizeof(ToolButtonInfo)
		- (FollowButton ? 0 : 2));
						
	Add(&m_TimeLabel);
	m_TimeLabel.SetWidget(&m_TimeEdit);
	m_TimeLabel.SetCaption(GetApp().LoadString(IDS_PREVIEW_FRAME));
	m_TimeLabel.SetAlignment(ALIGN_HLEFT|ALIGN_VTOP);

	Add(&m_FramerateLabel);
	m_FramerateLabel.SetWidget(&m_FramerateEdit);
	m_FramerateLabel.SetText(0, GetApp().LoadString(IDS_FRAMERATE));
	ClearRealFramerate();
	m_FramerateLabel.SetAlignment(ALIGN_HLEFT|ALIGN_VTOP);
}

TimeControls::~TimeControls()
{
}

CSize TimeControls::GetPreferredSize() const
{
	CSize s(Gap * 2, Gap * 2);
	s += m_Buttons.GetPreferredSize();
	s.cy += Gap + m_TimeLabel.GetPreferredSize().cy + m_FramerateLabel.GetPreferredSize().cy;
	return s;
}

void TimeControls::SetSequence(Sequence * ptr)
{
	m_TimeEdit.SetSequence(ptr);
}

void TimeControls::SetSequenceView(SequenceView * ptr)
{
	if (m_pSequenceView != ptr) {
		if (m_pSequenceView != 0)
			m_pSequenceView->Player::Detach(this);
		m_pSequenceView = ptr;
		if (m_pSequenceView != 0)
			m_pSequenceView->Player::Attach(this);
	}
	m_FramerateEdit.SetSequenceView(ptr);
}

void TimeControls::LayoutControls()
{
	CRect rClient = ClientRect();
	rClient.DeflateRect(Gap, Gap);

	CRect rButtons(CPoint(0, 0), m_Buttons.GetPreferredSize());
	rButtons = AlignRect(rClient, rButtons, ALIGN_HCENTER|ALIGN_VTOP);
	m_Buttons.SetBounds(rButtons);

	CRect rTime(rClient);
	rTime.top = rButtons.bottom + Gap;
	rTime.bottom = rTime.top + m_TimeLabel.GetPreferredSize().cy;
	m_TimeLabel.SetBounds(rTime);

	CRect rFramerate(rClient);
	rFramerate.top = rTime.bottom;
	rFramerate.bottom = rFramerate.top + m_FramerateLabel.GetPreferredSize().cy;
	m_FramerateLabel.SetBounds(rFramerate);
}

void TimeControls::SetRealFramerate(float fps)
{
	std::ostringstream out;
	out.setf(std::ios::fixed);
	out.precision(1);
	out << "fps (" << fps << " fps)";
	m_FramerateLabel.SetText(1, out.str());
}

void TimeControls::ClearRealFramerate()
{
	m_FramerateLabel.SetText(1, "fps");
}

void TimeControls::ProcessEvent(Event & e)
{
	if (e.Is<Player::PlaymodeChange>())
		ProcessEvent(UpdateUIEvent());
	Container::ProcessEvent(e);
}

} // My